home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / clang / pgp20src.zip / MORE.C < prev    next >
C/C++ Source or Header  |  1992-09-02  |  10KB  |  373 lines

  1. /*    more.c  - Unix-style "more" paging output for PGP.
  2.     PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
  3.  
  4.     (c) Copyright 1990-1992 by Philip Zimmermann.  All rights reserved.
  5.     The author assumes no liability for damages resulting from the use
  6.     of this software, even if the damage results from defects in this
  7.     software.  No warranty is expressed or implied.
  8.  
  9.     All the source code Philip Zimmermann wrote for PGP is available for
  10.     free under the "Copyleft" General Public License from the Free
  11.     Software Foundation.  A copy of that license agreement is included in
  12.     the source release package of PGP.  Code developed by others for PGP
  13.     is also freely available.  Other code that has been incorporated into
  14.     PGP from other sources was either originally published in the public
  15.     domain or was used with permission from the various authors.  See the
  16.     PGP User's Guide for more complete information about licensing,
  17.     patent restrictions on certain algorithms, trademarks, copyrights,
  18.     and export controls.  
  19. */
  20.  
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #ifdef UNIX
  26. #include <sys/types.h>
  27. #endif
  28. #include "mpilib.h"
  29. #include "language.h"
  30. #include "fileio.h"
  31. #include "pgp.h"
  32.  
  33. /* Prototype for getch() */
  34.  
  35. int getch( void );
  36.  
  37. #ifdef MSDOS
  38. #define DEFAULT_LINES    25    /* MSDOS actually has a 25-line screen */
  39. #else
  40. #define DEFAULT_LINES    24
  41. #endif /* MSDOS */
  42. #define DEFAULT_COLUMNS    80
  43.  
  44. int screen_lines = DEFAULT_LINES, screen_columns = DEFAULT_COLUMNS;
  45.  
  46. #define TAB        0x09        /* ASCII tab char */
  47. #define CR        '\r'        /* Carriage return char */
  48. #define LF        '\n'        /* Linefeed */
  49.  
  50. /* Get the screen size for 'more'.  The environment variables $LINES and
  51.    $COLUMNS will be used if they exist.  If not, then the TIOCGWINSZ call to
  52.    ioctl() is used (if it is defined).  If not, then the TIOCGSIZE call to
  53.    ioctl() is used (if it is defined).  If not, then the WIOCGETD call to
  54.    ioctl() is used (if it is defined).  If not, then get the info from
  55.    terminfo/termcap (if it is there).  Otherwise, assume we have a 24x80
  56.    model 33.
  57.  
  58.    That was for Unix.
  59.  
  60.    For DOS, just assume 24x80. */
  61.  
  62. #ifdef UNIX
  63. /* Try to access terminfo through the termcap-interface in the curses library
  64.    (which requires linking with -lcurses) or use termcap directly (which
  65.    requires linking with -ltermcap) */
  66.  
  67. #ifndef USE_TERMCAP
  68. #ifdef USE_TERMINFO
  69. #define USE_TERMCAP
  70. #endif
  71. #ifdef USE_CURSES
  72. #define USE_TERMCAP
  73. #endif
  74. #endif
  75.  
  76. #ifdef USE_TERMCAP
  77. #define TERMBUFSIZ    1024
  78. #define UNKNOWN_TERM  "unknown"
  79. #define DUMB_TERMBUF  "dumb:co#80:hc:"
  80.  
  81.   extern int  tgetent(), tgetnum();
  82. #endif
  83.  
  84. /* Try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
  85. #ifndef NOTERMIO
  86. #ifndef M_XENIX
  87. #include <termios.h>
  88. #else
  89. #include <termio.h>
  90. #endif /* not M_XENIX */
  91. #endif
  92.  
  93. #ifndef M_XENIX
  94. #ifndef TIOCGWINSZ
  95. #ifndef TIOCGSIZE
  96. #ifndef WIOCGETD
  97. #include <sys/ioctl.h>
  98. #endif /* not WIOCGETD */
  99. #endif /* not TIOCGSIZE */
  100. #endif /* not TIOCGWINSZ */
  101.  
  102. /* If we still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
  103. #ifndef TIOCGWINSZ
  104. #ifndef TIOCGSIZE
  105. #ifndef WIOCGETD
  106. #include <sgtty.h>
  107. #endif /* not WIOCGETD */
  108. #endif /* not TIOCGSIZE */
  109. #endif /* not TIOCGWINSZ */
  110. #endif /* not M_XENIX */
  111.  
  112. static void getScreenSize(void)    /* Rot bilong kargo */
  113. /* Return the screen size */
  114. {
  115.     char *envLines, *envColumns;
  116.     long rowTemp = 0, colTemp = 0;
  117. #ifdef USE_TERMCAP
  118.     char termBuffer[TERMBUFSIZ], *termInfo;
  119. #endif
  120. #ifdef TIOCGWINSZ
  121.     struct winsize windowInfo;
  122. #else
  123. #ifdef TIOCGSIZE
  124.     struct ttysize windowInfo;
  125. #else
  126. #ifdef WIOCGETD
  127.       struct uwdata windowInfo;
  128. #endif /* WIOCGETD */
  129. #endif /* TIOCGSIZE */
  130. #endif /* TIOCGWINSZ */
  131.  
  132.     /* Make sure that we're outputting to a terminal */
  133.     if (!isatty(fileno(stderr)))
  134.     {
  135.         screen_lines = DEFAULT_LINES;
  136.         screen_columns = DEFAULT_COLUMNS;
  137.         return;
  138.     }
  139.     screen_lines = screen_columns = 0;
  140.  
  141.     /* LINES & COLUMNS environment variables override everything else */
  142.     envLines = getenv("LINES");
  143.     if (envLines != NULL && (rowTemp = atol(envLines)) > 0 )
  144.         screen_lines = (int)rowTemp;
  145.  
  146.     envColumns = getenv("COLUMNS");
  147.     if (envColumns != NULL && (colTemp = atol(envColumns)) > 0 )
  148.         screen_columns = (int)colTemp;
  149.  
  150. #ifdef TIOCGWINSZ
  151.     /* See what ioctl() has to say (overrides terminfo & termcap) */
  152.     if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGWINSZ,&windowInfo) != -1)
  153.     {    if (!screen_lines && windowInfo.ws_row > 0)
  154.             screen_lines = (int)windowInfo.ws_row;
  155.  
  156.         if (!screen_columns && windowInfo.ws_col > 0 )
  157.             screen_columns = (int)windowInfo.ws_col;
  158.     }
  159. #else
  160. #ifdef TIOCGSIZE
  161.     /* See what ioctl() has to say (overrides terminfo & termcap) */
  162.     if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGSIZE,&windowInfo) != -1)
  163.     {    if (!screen_lines && windowInfo.ts_lines > 0)
  164.             screen_lines = (int)windowInfo.ts_lines;
  165.  
  166.         if (!screen_columns && windowInfo.ts_cols > 0)
  167.             screen_columns = (int)windowInfo.ts_cols;
  168.     }
  169. #else
  170. #ifdef WIOCGETD
  171.     /* See what ioctl() has to say (overrides terminfo & termcap) */
  172.     if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),WIOCGETD,&windowInfo) != -1)
  173.     {    if (!screen_lines && windowInfo.uw_height > 0)
  174.             screen_lines = (int)(windowInfo.uw_height / windowInfo.uw_vs);
  175.  
  176.         if (!screen_columns && windowInfo.uw_width > 0)
  177.             screen_columns = (int)(windowInfo.uw_width / windowInfo.uw_hs);
  178.     }    /* You are in a twisty maze of standards, all different */
  179. #endif
  180. #endif
  181. #endif
  182.  
  183. #ifdef USE_TERMCAP
  184.     /* See what terminfo/termcap has to say */
  185.     if (!screen_lines || !screen_columns)
  186.     {    if ((termInfo = getenv("TERM")) == (char *)NULL)
  187.             termInfo = UNKNOWN_TERM;
  188.  
  189.         if ((tgetent(termBuffer, termInfo) <= 0))
  190.             strcpy(termBuffer,DUMB_TERMBUF);
  191.  
  192.         if (!screen_lines && (rowTemp = tgetnum("li")) > 0)
  193.                 screen_lines = (int)rowTemp;
  194.  
  195.         if (!screen_columns && (colTemp = tgetnum("co")) > 0)
  196.                 screen_columns = (int)colTemp;
  197.     }
  198. #endif
  199.     if (screen_lines == 0)            /* nothing worked, use defaults */
  200.         screen_lines = DEFAULT_LINES;
  201.     if (screen_columns == 0)
  202.         screen_columns = DEFAULT_COLUMNS;
  203. }
  204. #else
  205. #define getScreenSize()
  206. #endif /* UNIX */
  207.  
  208. /* Certain systems need to go into a "break" mode */
  209. #ifdef UNIX
  210. #define    NEEDBREAK
  211. #endif
  212. #ifdef AMIGA
  213. #define NEEDBREAK
  214. #endif
  215. #ifdef ATARI
  216. #define reverse_attr()        printf("\033p")
  217. #define norm_attr()            printf("\033q")
  218. #else
  219. #define reverse_attr()
  220. #define norm_attr()
  221. #endif
  222.  
  223. char pager[80] = "";
  224.  
  225. int more_file(char *fileName)
  226. /* Blort a file to the screen with page breaks, intelligent handling of line
  227.    terminators, truncation of overly long lines, and zapping of illegal
  228.    chars */
  229. {
  230.     FILE *inFile;
  231.     int lines = 0,ch,i,chars = 0, c;
  232.     long fileLen;
  233.     char cmd[MAX_PATH];
  234.     char buf[16];
  235.     int lineno;
  236.     char *p;
  237.  
  238.     if ((inFile = fopen(fileName,"rb")) == NULL)
  239.         /* Can't see how this could fail since we just created the file */
  240.         return(-1);
  241.  
  242.     fread(buf, 1, 16, inFile);
  243.     if (compressSignature(buf) >= 0)
  244.     {    fprintf(pgpout, PSTR("\n\007File '%s' is not a text file; cannot display.\n"),
  245.                     fileName);
  246.         return(-1);
  247.     }
  248.  
  249.     /* PAGER set in config.txt overrides environment variable, 
  250.         set PAGER in config.txt to 'pgp' to use builtin pager */
  251.     if (pager[0] == '\0')
  252.     {
  253.         if ((p = getenv("PAGER")) != NULL)
  254.             strncpy(pager, p, sizeof(pager) - 1);
  255.     }
  256.     /* Use built-in pager if PAGER is not set or if this is for your eyes only */
  257.     if ((strcmp(fileName,CONSOLE_FILENAME) != 0)
  258.         && (strlen(pager) != 0) && strcmp("pgp", pager))
  259.     {
  260.         fclose(inFile);
  261. #ifdef UNIX
  262.         if (strchr(fileName, '\'') != NULL)
  263.             return(-1);
  264.         sprintf(cmd, "%s '%s'", pager, fileName);
  265. #else
  266.         sprintf(cmd, "%s %s", pager, fileName);
  267. #ifdef MSDOS
  268.         for (p = cmd; *p; ++p)
  269.             if (*p == '/')
  270.                 *p = '\\';
  271. #endif
  272. #endif
  273.         return(system(cmd));
  274.     }
  275.  
  276.     getScreenSize();
  277.  
  278.     /* Get file length */
  279.     fseek(inFile,0L,SEEK_END);
  280.     fileLen = ftell(inFile);
  281.     rewind(inFile);
  282.     lineno = 1;
  283.  
  284. #ifdef NEEDBREAK
  285.     ttycbreak();
  286. #endif
  287.     putchar('\n');
  288.     while (TRUE)
  289.     {   ch = getc(inFile);
  290.         if (ch == LF)
  291.         {   lines++;
  292.             putchar('\n');
  293.             chars = 0;
  294.             ++lineno;
  295.         }
  296.         else
  297.             if (ch == CR)
  298.             {   lines++;
  299.                 putchar('\n');
  300.                 chars = 0;
  301.                 ++lineno;
  302.  
  303.                 /* Skip following LF if there is one */
  304.                 if ((ch = getc(inFile)) != LF && ch != EOF)
  305.                     ungetc(ch,inFile);
  306.             }
  307.             else
  308.                 if (((unsigned char) ch >= ' ' && ch != EOF) || ch == TAB)
  309.                 {   /* Legal char or tab, print it */
  310.                     putchar(ch);
  311.                     chars += (ch == TAB) ? 8 : 1;
  312.                 }
  313.  
  314.         /* If we've reach the max.no of columns we can handle, skip the
  315.            rest of the line */
  316.         if (chars == screen_columns - 1)
  317.         {    chars = 0;
  318.             while ((ch = getc(inFile)) != CR && ch != LF && ch != EOF );
  319.             if (ch != EOF)
  320.                 ungetc(ch,inFile);
  321.         }
  322.  
  323.         /* If we've reached the max.no of rows we can handle, wait for the
  324.            user to hit a key */
  325.         while (ch == EOF || lines == screen_lines - 1)
  326.         {    /* Print prompt at end of screen */
  327.             reverse_attr();
  328.             if (ch == EOF)
  329.                 printf(PSTR("\nDone...hit any key\r"));
  330.             else
  331.                 printf(PSTR("More -- %d%% -- Hit space for next screen, Enter for new line, 'Q' to quit --\r"),
  332.                     ( 100 * ftell( inFile ) ) / fileLen );
  333.             norm_attr();
  334.             fflush(stdout);
  335.             c = getch();
  336.             c = toupper(c);
  337.  
  338.             /* Blank out prompt */
  339.             for (i=0; i<79; i++)
  340.                 putchar(' ');
  341.             putchar('\r');
  342.             fflush(stdout);
  343.             if (c == 'B' && lineno > screen_lines)        /* go Back a page */
  344.             {    int seek_line = lineno - 2*screen_lines + 3;
  345.                 lineno = 1;
  346.                 rewind(inFile);
  347.                 if (seek_line > 1)
  348.                 {    printf("...skipping\n");
  349.                     while ((ch = getc(inFile)) != EOF)
  350.                         if (ch == '\n')
  351.                             if (++lineno == seek_line)
  352.                                 break;
  353.                 }
  354.                 ch = '\0';
  355.                 lines = 0;
  356.             }
  357.             else
  358.             {    if (c == 'Q' || ch == EOF)
  359.                     goto done;
  360.                 if (c == ' ' || c == '\n' || c == '\r' || c == 'J')
  361.                     lines -= (c == ' ') ? screen_lines - 2 : 1;    /* Do n more lines */
  362.             }
  363.         }
  364.     }
  365. done:
  366. #ifdef NEEDBREAK
  367.     ttynorm();
  368. #endif
  369.     fclose(inFile);
  370.     return(0);
  371. } /* more_file */
  372.  
  373.